package org.zhengquan.service;

import com.google.common.base.Preconditions;
import org.apache.commons.lang3.StringUtils;
import org.codehaus.jackson.type.TypeReference;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.zhengquan.common.LogType;
import org.zhengquan.common.RequestHolder;
import org.zhengquan.dao.*;
import org.zhengquan.dto.PageResult;
import org.zhengquan.dto.SearchLogDto;
import org.zhengquan.exception.ParamException;
import org.zhengquan.pojo.*;
import org.zhengquan.util.BeanValidator;
import org.zhengquan.util.DateTimeUtil;
import org.zhengquan.util.IpUtil;
import org.zhengquan.util.JsonMapper;
import org.zhengquan.vo.PageQuery;
import org.zhengquan.vo.SearchLogVo;

import java.util.Date;
import java.util.List;

/**
 * @author zhengquan
 * @date 2017/11/6
 */
@Service
public class SysLogService {

    @Autowired
    private SysLogMapper sysLogMapper;

    @Autowired
    private SysDeptMapper sysDeptMapper;

    @Autowired
    private SysUserMapper sysUserMapper;

    @Autowired
    private SysAclModuleMapper sysAclModuleMapper;

    @Autowired
    private SysAclMapper sysAclMapper;

    @Autowired
    private SysRoleMapper sysRoleMapper;

    @Autowired
    private SysRoleAclService sysRoleAclService;

    @Autowired
    private SysRoleUserService sysRoleUserService;

    public void recover(Integer id){
        SysLogWithBLOBs sysLogWithBLOBs = sysLogMapper.selectByPrimaryKey(id);
        Preconditions.checkNotNull(sysLogWithBLOBs,"待还原记录不存在");
        switch (sysLogWithBLOBs.getType()){
            case LogType.TYPE_DEPT:
                SysDept beforeDept = sysDeptMapper.selectByPrimaryKey(sysLogWithBLOBs.getTargetId());
                Preconditions.checkNotNull(beforeDept,"待还原的部门不存在");
                if(StringUtils.isBlank(sysLogWithBLOBs.getNewValue()) ||StringUtils.isBlank(sysLogWithBLOBs.getOldValue())){
                    throw new ParamException("新增和删除操作不做还原");
                }
                SysDept afterDept =JsonMapper.str2Obj(sysLogWithBLOBs.getOldValue(), new TypeReference<SysDept>() {});
                afterDept.setOperator(RequestHolder.getCurrentUser().getUsername());
                afterDept.setOperateTime(new Date());
                afterDept.setOperateIp(IpUtil.getRemoteIp(RequestHolder.getCurrentRequest()));
                sysDeptMapper.updateByPrimaryKey(afterDept);
                saveDeptLog(beforeDept,afterDept);
                break;
            case LogType.TYPE_USER:
                SysUser beforeUser = sysUserMapper.selectByPrimaryKey(sysLogWithBLOBs.getTargetId());
                Preconditions.checkNotNull(beforeUser,"待还原的用户不存在");
                if(StringUtils.isBlank(sysLogWithBLOBs.getNewValue()) ||StringUtils.isBlank(sysLogWithBLOBs.getOldValue())){
                    throw new ParamException("新增和删除操作不做还原");
                }
                SysUser afterUser =JsonMapper.str2Obj(sysLogWithBLOBs.getOldValue(), new TypeReference<SysUser>() {});
                afterUser.setOperator(RequestHolder.getCurrentUser().getUsername());
                afterUser.setOperateTime(new Date());
                afterUser.setOperateIp(IpUtil.getRemoteIp(RequestHolder.getCurrentRequest()));
                sysUserMapper.updateByPrimaryKey(afterUser);
                saveUserLog(beforeUser,afterUser);
                break;
            case LogType.TYPE_ACL_MODULE:
                SysAclModule beforeAclModule = sysAclModuleMapper.selectByPrimaryKey(sysLogWithBLOBs.getTargetId());
                Preconditions.checkNotNull(beforeAclModule,"待还原的权限模块不存在");
                if(StringUtils.isBlank(sysLogWithBLOBs.getNewValue()) ||StringUtils.isBlank(sysLogWithBLOBs.getOldValue())){
                    throw new ParamException("新增和删除操作不做还原");
                }
                SysAclModule afterAclModule =JsonMapper.str2Obj(sysLogWithBLOBs.getOldValue(), new TypeReference<SysAclModule>() {});
                afterAclModule.setOperator(RequestHolder.getCurrentUser().getUsername());
                afterAclModule.setOperateTime(new Date());
                afterAclModule.setOperateIp(IpUtil.getRemoteIp(RequestHolder.getCurrentRequest()));
                sysAclModuleMapper.updateByPrimaryKey(afterAclModule);
                saveAclModuleLog(beforeAclModule,afterAclModule);
                break;
            case LogType.TYPE_ACL:
                SysAcl beforeAcl = sysAclMapper.selectByPrimaryKey(sysLogWithBLOBs.getTargetId());
                Preconditions.checkNotNull(beforeAcl,"待还原的权限点不存在");
                if(StringUtils.isBlank(sysLogWithBLOBs.getNewValue()) ||StringUtils.isBlank(sysLogWithBLOBs.getOldValue())){
                    throw new ParamException("新增和删除操作不做还原");
                }
                SysAcl afterAcl =JsonMapper.str2Obj(sysLogWithBLOBs.getOldValue(), new TypeReference<SysAcl>() {});
                afterAcl.setOperator(RequestHolder.getCurrentUser().getUsername());
                afterAcl.setOperateTime(new Date());
                afterAcl.setOperateIp(IpUtil.getRemoteIp(RequestHolder.getCurrentRequest()));
                sysAclMapper.updateByPrimaryKey(afterAcl);
                saveAclLog(beforeAcl,afterAcl);
                break;
            case LogType.TYPE_ROLE:
                SysRole beforeRole = sysRoleMapper.selectByPrimaryKey(sysLogWithBLOBs.getTargetId());
                Preconditions.checkNotNull(beforeRole,"待还原的角色不存在");
                if(StringUtils.isBlank(sysLogWithBLOBs.getNewValue()) ||StringUtils.isBlank(sysLogWithBLOBs.getOldValue())){
                    throw new ParamException("新增和删除操作不做还原");
                }
                SysRole afterRole =JsonMapper.str2Obj(sysLogWithBLOBs.getOldValue(), new TypeReference<SysRole>() {});
                afterRole.setOperator(RequestHolder.getCurrentUser().getUsername());
                afterRole.setOperateTime(new Date());
                afterRole.setOperateIp(IpUtil.getRemoteIp(RequestHolder.getCurrentRequest()));
                sysRoleMapper.updateByPrimaryKey(afterRole);
                saveRoleLog(beforeRole,afterRole);
                break;
            case LogType.TYPE_ROLE_ACL:
                SysRole aclRole = sysRoleMapper.selectByPrimaryKey(sysLogWithBLOBs.getTargetId());
                Preconditions.checkNotNull(aclRole,"角色不存在");
                sysRoleAclService.changeRoleAcls(sysLogWithBLOBs.getTargetId(),JsonMapper.str2Obj(sysLogWithBLOBs.getOldValue(), new TypeReference<List<Integer>>() {}));
                break;
            case LogType.TYPE_ROLE_USER:
                SysRole userRole = sysRoleMapper.selectByPrimaryKey(sysLogWithBLOBs.getTargetId());
                Preconditions.checkNotNull(userRole,"角色不存在");
                sysRoleUserService.changeRoleUsers(sysLogWithBLOBs.getTargetId(),JsonMapper.str2Obj(sysLogWithBLOBs.getOldValue(), new TypeReference<List<Integer>>() {}));
                break;
            default:break;
        }
    }


    public PageResult<SysLogWithBLOBs> searchPageList(SearchLogVo searchLogVo, PageQuery pageQuery) {
        BeanValidator.check(pageQuery);
        SearchLogDto searchLogDto = new SearchLogDto();
        searchLogDto.setType(searchLogVo.getType());
        if (StringUtils.isNotBlank(searchLogVo.getBeforeSeg())) {
            searchLogDto.setBeforeSeg("%" + searchLogVo.getBeforeSeg() + "%");
        }
        if (StringUtils.isNotBlank(searchLogVo.getAfterSeg())) {
            searchLogDto.setAfterSeg("%" + searchLogVo.getAfterSeg() + "%");
        }
        if (StringUtils.isNotBlank(searchLogVo.getOperator())) {
            searchLogDto.setOperator("%" + searchLogVo.getOperator() + "%");
        }
        if (StringUtils.isNotBlank(searchLogVo.getFromTime())) {
            searchLogDto.setFromTime(DateTimeUtil.strToDate(searchLogVo.getFromTime()));
        }
        if (StringUtils.isNotBlank(searchLogVo.getToTime())) {
            searchLogDto.setToTime(DateTimeUtil.strToDate(searchLogVo.getToTime()));
        }
        int count = sysLogMapper.countBySearchDto(searchLogDto);
        if (count > 0) {
            List<SysLogWithBLOBs> logList = sysLogMapper.selectPageListBySearchDto(searchLogDto, pageQuery);
            return PageResult.<SysLogWithBLOBs>builder().total(count).data(logList).build();
        }
        return PageResult.<SysLogWithBLOBs>builder().build();
    }

    public void saveDeptLog(SysDept before, SysDept after) {
        SysLogWithBLOBs sysLogWithBLOBs = new SysLogWithBLOBs();
        sysLogWithBLOBs.setType(LogType.TYPE_DEPT);
        sysLogWithBLOBs.setTargetId(after == null ? before.getId() : after.getId());
        sysLogWithBLOBs.setOldValue(before == null ? "" : JsonMapper.obj2Str(before));
        sysLogWithBLOBs.setNewValue(after == null ? "" : JsonMapper.obj2Str(after));
        sysLogWithBLOBs.setOperator(RequestHolder.getCurrentUser().getUsername());
        sysLogWithBLOBs.setOperateTime(new Date());
        sysLogWithBLOBs.setOperateIp(IpUtil.getRemoteIp(RequestHolder.getCurrentRequest()));
        sysLogMapper.insertSelective(sysLogWithBLOBs);
    }

    public void saveUserLog(SysUser before, SysUser after) {
        SysLogWithBLOBs sysLogWithBLOBs = new SysLogWithBLOBs();
        sysLogWithBLOBs.setType(LogType.TYPE_USER);
        sysLogWithBLOBs.setTargetId(after == null ? before.getId() : after.getId());
        sysLogWithBLOBs.setOldValue(before == null ? "" : JsonMapper.obj2Str(before));
        sysLogWithBLOBs.setNewValue(after == null ? "" : JsonMapper.obj2Str(after));
        sysLogWithBLOBs.setOperator(RequestHolder.getCurrentUser().getUsername());
        sysLogWithBLOBs.setOperateTime(new Date());
        sysLogWithBLOBs.setOperateIp(IpUtil.getRemoteIp(RequestHolder.getCurrentRequest()));
        sysLogMapper.insertSelective(sysLogWithBLOBs);
    }

    public void saveAclModuleLog(SysAclModule before, SysAclModule after) {
        SysLogWithBLOBs sysLogWithBLOBs = new SysLogWithBLOBs();
        sysLogWithBLOBs.setType(LogType.TYPE_ACL_MODULE);
        sysLogWithBLOBs.setTargetId(after == null ? before.getId() : after.getId());
        sysLogWithBLOBs.setOldValue(before == null ? "" : JsonMapper.obj2Str(before));
        sysLogWithBLOBs.setNewValue(after == null ? "" : JsonMapper.obj2Str(after));
        sysLogWithBLOBs.setOperator(RequestHolder.getCurrentUser().getUsername());
        sysLogWithBLOBs.setOperateTime(new Date());
        sysLogWithBLOBs.setOperateIp(IpUtil.getRemoteIp(RequestHolder.getCurrentRequest()));
        sysLogMapper.insertSelective(sysLogWithBLOBs);
    }

    public void saveAclLog(SysAcl before, SysAcl after) {
        SysLogWithBLOBs sysLogWithBLOBs = new SysLogWithBLOBs();
        sysLogWithBLOBs.setType(LogType.TYPE_ACL);
        sysLogWithBLOBs.setTargetId(after == null ? before.getId() : after.getId());
        sysLogWithBLOBs.setOldValue(before == null ? "" : JsonMapper.obj2Str(before));
        sysLogWithBLOBs.setNewValue(after == null ? "" : JsonMapper.obj2Str(after));
        sysLogWithBLOBs.setOperator(RequestHolder.getCurrentUser().getUsername());
        sysLogWithBLOBs.setOperateTime(new Date());
        sysLogWithBLOBs.setOperateIp(IpUtil.getRemoteIp(RequestHolder.getCurrentRequest()));
        sysLogMapper.insertSelective(sysLogWithBLOBs);
    }

    public void saveRoleLog(SysRole before, SysRole after) {
        SysLogWithBLOBs sysLogWithBLOBs = new SysLogWithBLOBs();
        sysLogWithBLOBs.setType(LogType.TYPE_ROLE);
        sysLogWithBLOBs.setTargetId(after == null ? before.getId() : after.getId());
        sysLogWithBLOBs.setOldValue(before == null ? "" : JsonMapper.obj2Str(before));
        sysLogWithBLOBs.setNewValue(after == null ? "" : JsonMapper.obj2Str(after));
        sysLogWithBLOBs.setOperator(RequestHolder.getCurrentUser().getUsername());
        sysLogWithBLOBs.setOperateTime(new Date());
        sysLogWithBLOBs.setOperateIp(IpUtil.getRemoteIp(RequestHolder.getCurrentRequest()));
        sysLogMapper.insertSelective(sysLogWithBLOBs);
    }

}
